package com.example.demo.nio;

import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.AsyncContext;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Configuration
public class LocalNewsPoolConfig {
    private final static Logger LOG= LoggerFactory.getLogger(LocalNewsPoolConfig.class);

    @Bean
    public ThreadPoolExecutor init(){
        int corePoolSize= 10;
        int maximumPoolSize= 100;
        int queueCapacity= 200;
        LinkedBlockingDeque<Runnable> queue= new LinkedBlockingDeque<>(queueCapacity);
        ThreadPoolExecutor executor= new ThreadPoolExecutor(corePoolSize,maximumPoolSize,60L, TimeUnit.SECONDS,queue);
        executor.allowCoreThreadTimeOut(true);
        executor.setRejectedExecutionHandler((r, executor1) -> {
            if(r instanceof CustomCallable){
                CustomCallable call= (CustomCallable) r;
                AsyncContext asyncContext= call.asyncContext;
                if(asyncContext!=null){
                    handler(asyncContext);
                }
            }
        });
        return executor;
    }

    private static void handler(AsyncContext asyncContext){
        try{
            ServletRequest req= asyncContext.getRequest();
            String uri= (String) req.getAttribute(Constant.URI);
            Map params= (Map) req.getAttribute(Constant.PARAMS);
            LOG.error("async req rejected. uri :{},params:{}",uri, JSON.toJSONString(params));
        }catch (Exception e){
            e.printStackTrace();
            try{
                HttpServletResponse response= (HttpServletResponse) asyncContext.getResponse();
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            }catch (Exception e1){}
        }finally {
            asyncContext.complete();
        }
    }


}
